﻿using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using SpecFlowTfsLinker.Entities;
using SpecFlowTfsLinker.Printer;
using SpecFlowTfsLinker.Test.Common;
using SpecFlowTfsLinker.Test.Resources;

namespace SpecFlowTfsLinker.Test.Printer
{
    [TestFixture]
    public class StepDefinitionPrinterTest : TestInitialization
    {
        private static StepDefinitionPrinter _printerUsCalculation;

        [SetUp]
        public void Init()
        {
            Initialize();
            _printerUsCalculation = new StepDefinitionPrinter(UserStoryResources.Calculation.CompleteUserStory);
        }

        [Test]
        public void CanDisplayNameFromUserStory()
        {
            Assert.That(_printerUsCalculation.UserStoryTitle, Is.EqualTo(UserStoryResources.Calculation.CleanedTitle));
        }

        [Test]
        public void CanDisplayTypeFromUserStoryNoParameter()
        {
            var printer = new StepDefinitionPrinter(UserStoryResources.Bowling.CompleteUserStory);
            foreach (var testCase in printer.TestCases)
            {
                if (testCase.Given.Count > 0)
                    Assert.AreEqual(StatementType.Given, testCase.Given[0].DisplayType);
                if (testCase.When.Count > 0)
                    Assert.AreEqual(StatementType.When, testCase.When[0].DisplayType);
                if (testCase.Then.Count > 0)
                    Assert.AreEqual(StatementType.Then, testCase.Then[0].DisplayType);
            }
        }

        [Test]
        public void CanDisplayGivenAndAndFromUserStory()
        {
            _printerUsCalculation.TestCases.ForEach(testCase => testCase.Given.ForEach(given => Assert.AreEqual(StatementType.Given, given.DisplayType)));
        }

        [Test]
        public void CanDisplayWhenAndAndFromUserStory()
        {
            _printerUsCalculation.TestCases.ForEach(testCase => testCase.When.ForEach(when => Assert.AreEqual(StatementType.When, when.DisplayType)));
        }

        [Test]
        public void CanDisplayThenAndAndFromUserStory()
        {
            _printerUsCalculation.TestCases.ForEach(testCase => testCase.Then.ForEach(then => Assert.AreEqual(StatementType.Then, then.DisplayType)));
        }

        [Test]
        public void CanDisplayGivenParameterFromUserStory()
        {
            var results = GetParametersResultFrom(StatementType.Given);
            Assert.AreEqual(TestCaseResources.Addition.Given.Parameters, results[0]);
            Assert.AreEqual(TestCaseResources.Addition.GivenAnd.Parameters, results[1]);
            Assert.AreEqual(TestCaseResources.Addition.GivenSecondAnd.Parameters, results[2]);
        }

        [Test]
        public void CanDisplayWhenParameterFromUserStory()
        {
            var results = GetParametersResultFrom(StatementType.When);
            Assert.AreEqual(TestCaseResources.Addition.When.Parameters, results[0]);
            Assert.AreEqual(TestCaseResources.Addition.WhenAnd.Parameters, results[1]);
        }

        [Test]
        public void CanDisplayThenParameterFromUserStory()
        {
            var results = GetParametersResultFrom(StatementType.Then);
            Assert.AreEqual(TestCaseResources.Addition.Then.Parameters, results[0]);
            Assert.AreEqual(TestCaseResources.Addition.ThenAnd.Parameters, results[1]);
        }

        [Test]
        public void CanDisplayGivenStatementFromUserStory()
        {
            var testCase = _printerUsCalculation.TestCases.First();
            Assert.AreEqual(TestCaseResources.Addition.Given.FinalMethodStatement, testCase.Given[0].DisplayMethodStatement);
            Assert.AreEqual(TestCaseResources.Addition.GivenAnd.FinalMethodStatement, testCase.Given[1].DisplayMethodStatement);
            Assert.AreEqual(TestCaseResources.Addition.GivenSecondAnd.FinalMethodStatement, testCase.Given[2].DisplayMethodStatement);
        }

        [Test]
        public void CanDisplayWhenStatementFromUserStory()
        {
            var testCase = _printerUsCalculation.TestCases.First();
            Assert.AreEqual(TestCaseResources.Addition.When.FinalMethodStatement, testCase.When[0].DisplayMethodStatement);
            Assert.AreEqual(TestCaseResources.Addition.WhenAnd.FinalMethodStatement, testCase.When[1].DisplayMethodStatement);
        }

        [Test]
        public void CanDisplayThenStatementFromUserStory()
        {
            var testCase = _printerUsCalculation.TestCases.First();
            Assert.AreEqual(TestCaseResources.Addition.Then.FinalMethodStatement, testCase.Then[0].DisplayMethodStatement);
            Assert.AreEqual(TestCaseResources.Addition.ThenAnd.FinalMethodStatement, testCase.Then[1].DisplayMethodStatement);
        }

        [Test]
        public void CannotDisplayDuplicatedStatement()
        {
            Assert.IsTrue(_printerUsCalculation.TestCases.Count == 2);
            Assert.IsTrue(_printerUsCalculation.TestCases[1].Given.Count == 0);
            Assert.IsTrue(_printerUsCalculation.TestCases[1].When.Count == 0);
            Assert.IsTrue(_printerUsCalculation.TestCases[1].Then.Count == 0);
        }

        [Test]
        public void CanDisPlayGivenMethod()
        {
            Assert.AreEqual(TestCaseResources.Addition.Given.CompleteMethodHeader, _printerUsCalculation.TestCases[0].Given[0].DisplayMethod);
            Assert.AreEqual(TestCaseResources.Addition.GivenAnd.CompleteMethodHeader, _printerUsCalculation.TestCases[0].Given[1].DisplayMethod);
            Assert.AreEqual(TestCaseResources.Addition.GivenSecondAnd.CompleteMethodHeader, _printerUsCalculation.TestCases[0].Given[2].DisplayMethod);
            //Assert.AreEqual(TestResource.Addition.GivenAnd.Method, StepDefinitionPrinter.DisPlayMethod(1, 1, _printerUsCalculation.TestCases[0].Given[1]));
            //Assert.AreEqual(TestResource.Addition.GivenSecondAnd.Method, StepDefinitionPrinter.DisPlayMethod(1, 1, _printerUsCalculation.TestCases[0].Given[2]));
        }

        [Test]
        public void CanDisPlayWhenMethod()
        {
            //Assert.AreEqual(TestResource.Addition.When.Method, StepDefinitionPrinter.DisPlayMethod(1, 1, _printerUsCalculation.TestCases[0].When[0]));
            //Assert.AreEqual(TestResource.Addition.WhenAnd.Method, StepDefinitionPrinter.DisPlayMethod(1, 1, _printerUsCalculation.TestCases[0].When[1]));
        }

        [Test]
        public void CanDisPlayThenMethod()
        {
            //Assert.AreEqual(TestResource.Addition.Then.Method, StepDefinitionPrinter.DisPlayMethod(1, 1, _printerUsCalculation.TestCases[0].Then[0]));
            //Assert.AreEqual(TestResource.Addition.ThenAnd.Method, StepDefinitionPrinter.DisPlayMethod(1, 1, _printerUsCalculation.TestCases[0].Then[1]));
        }

        [Test]
        public void CanDisplayUserStory()
        {
            //Assert.AreEqual(TestResource.Calculation.Print, _printerUsCalculation.ToString());
        }

        private static List<string> GetParametersResultFrom(StatementType type)
        {
            var results = new List<string>();
            _printerUsCalculation.TestCases.ForEach(testCase =>
            {
                List<StatementPrinter> statementList;
                if (type == StatementType.Given)
                    statementList = testCase.Given;
                else if (type == StatementType.When)
                    statementList = testCase.When;
                else statementList = testCase.Then;

                statementList.ForEach(given =>
                                      results.Add(given.DisplayParameters));
            });

            return results;
        }


    }
}